﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using InTheHand.Net;
using InTheHand.Net.Bluetooth;
using Brecham.Obex;
using InTheHand.Net.Sockets;

namespace BlueAd
{
    public class Comm : List<BluetoothDeviceInfo>
    {
        private BluetoothClient _client;
        private Thread _searchEngine;
        private Object _locker;
        private bool _running;
        public int SearchDelay { get; set; }
        public event EventHandler<OnDone> OnFinish;
        public bool Listening { get { return _searchEngine.IsAlive; } }

        public Comm()
        {
            try
            {
                _client = new BluetoothClient();
            }
            catch (Exception exception)
            {
                throw new Exception(exception.Message);
            }

            _searchEngine = new Thread(SearchDevices);
            _locker = new object();
            SearchDelay = 60000;
        }

        public void Start()
        {
            _running = true;
            if (_searchEngine.ThreadState != ThreadState.Running)
            {
                _searchEngine = new Thread(SearchDevices);
                _searchEngine.Start();
            }
        }

        public void Stop()
        {
            _running = false;
            _searchEngine.Abort();
        }


        private void SearchDevices()
        {
            while (_running)
            {
                lock (_locker)
                {
                    BluetoothDeviceInfo[] devices = _client.DiscoverDevices();
                    Clear();
                    if (devices.Any())
                    {
                        foreach (BluetoothDeviceInfo bluetoothDeviceInfo in devices)
                        {
                            Add(bluetoothDeviceInfo);
                        }
                        if (OnFinish != null)
                            OnFinish(this, null);
                    }
                }
                Thread.Sleep(SearchDelay);
            }
        }

        public BluetoothDeviceInfo this[string deviceName]
        {
            get
            {
                foreach (BluetoothDeviceInfo deviceInfo in this)
                {
                    if (deviceInfo.DeviceName.Equals(deviceName))
                        return deviceInfo;
                }
                return null;
            }
        }

        public void SendFile(FileInfo file, List<BluetoothDeviceInfo> devices)
        {
            lock (_locker)
            {
                List<BluetoothDeviceInfo> deviceInfos = devices.Any() ? devices : this;

                foreach (BluetoothDeviceInfo bluetoothDeviceInfo in deviceInfos)
                {
                    BluetoothAddress address = bluetoothDeviceInfo.DeviceAddress;
                    Uri uri = new Uri("obex://" + address + "/" + file.Name);
                    ObexWebRequest request = new ObexWebRequest(uri);
                    request.ReadFile(file.FullName);
                    ObexWebResponse response = (ObexWebResponse)request.GetResponse();
                    response.Close();
                }
            }
        }


        public void SendCampain(Campain campain)
        {
            SendCampain(campain, this);
        }

        public void SendCampain(Campain campain, List<BluetoothDeviceInfo> devices)
        {
            if (campain.Files.Any() && devices.Any())
            {
                lock (_locker)
                {
                    foreach (BluetoothDeviceInfo device in devices)
                    {
                        if (!campain.SendedDevices.Contains(device))
                        {
                            try
                            {
                                CampainToDeviceSender sender = new CampainToDeviceSender(SendCampainToDevice);
                                sender.BeginInvoke(campain, device, new AsyncCallback(AfterSend), "");
                            }
                            catch (Exception exception)
                            {
                                throw new Exception(exception.Message);
                            }
                        }
                    }
                }
            }
        }

        delegate void CampainToDeviceSender(Campain campain, BluetoothDeviceInfo device);

        public void SendCampainToDevice(Campain campain, BluetoothDeviceInfo device)
        {
            try
            {
                BluetoothAddress address = device.DeviceAddress;
                Uri uri = new Uri("obex://" + address + "/" + campain.Files[0]);
                ObexWebRequest request = new ObexWebRequest(uri);
                request.ReadFile(campain.Files[0].FullName);
                ObexWebResponse response = (ObexWebResponse)request.GetResponse();
                response.Close();
                campain.SendedDevices.Add(device);
            }
            catch (Exception exception)
            {
                return;
                throw new Exception(exception.Message);
            }
        }

        static void AfterSend(IAsyncResult result)
        {

        }

        public class OnDone : EventArgs
        {
            private List<BluetoothDeviceInfo> devices { get; set; }

        }
    }
}
